//------------------------------------------------------------------------------
// Utils.h
//------------------------------------------------------------------------------
// File provided for Microsoft Shared Source.
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
// PARTICULAR PURPOSE.
//------------------------------------------------------------------------------
//
// Utility function declarations
//
//------------------------------------------------------------------------------

#pragma once

////////////////////////////////////////////////////////////////////////////////

template <UINT uiID, class T, class ET, const IID *pdiid = &__uuidof(ET)>
class CDTEEventSinkBase :
    public IDispEventImpl<uiID, T, pdiid, &__uuidof(__EnvDTE), 8, 0>
{
public:
    CDTEEventSinkBase() {}
    ~CDTEEventSinkBase() { Disconnect(); }

    HRESULT Connect(__in DTE2 *pvsDTE2)
    {
        Disconnect();

        CComPtr<Events> spvsEvents;
        HRESULT hr = pvsDTE2->get_Events(&spvsEvents);
        if (SUCCEEDED(hr))
        {
            CComPtr<Events2> spvsEvents2;
            hr = spvsEvents->QueryInterface(&spvsEvents2);
            if (SUCCEEDED(hr))
            {
                hr = GetEventSourceObject(spvsEvents2, IID_IUnknown, (void **)&_spunkSource);
                if (SUCCEEDED(hr))
                {
                    hr = DispEventAdvise(_spunkSource);
                }
            }
        }
        return hr;
    }

    void Disconnect()
    {
        if (_spunkSource)
        {
            DispEventUnadvise(_spunkSource);
            _spunkSource = NULL;
        }
    }

protected:
    virtual HRESULT GetEventSourceObject(__in Events2 *pvsEvents2, REFIID riid, __deref_out void **ppv) = 0;

private:
    CComPtr<IUnknown> _spunkSource;
};

// Must use this as initial value for CRC
#define CRC32_INITIAL_VALUE 0L


//  CRC32Compute - Compute 32-bit crc value
//
//  Parameters:
//      pb    - Pointer to buffer to computer CRC on
//      cb    - Count of bytes in buffer to CRC
//      crc32 - Result from previous CRC32Compute call (on first call
//              to CRC32Compute, must be CRC32_INITIAL_VALUE!!!!).
//
//  Returns:
//      Updated CRC value.
//
ULONG CRC32Compute(const BYTE *pb, UINT cb, ULONG crc32);

#if WINVER<0x0600

#ifndef IID_PPV_ARGS
//  IID_PPV_ARGS(ppType)
//      ppType is the variable of type IType that will be filled
//
//      RESULTS in:  IID_IType, ppvType
//      will create a compiler error if wrong level of indirection is used.
//
extern "C++"
{
    template<typename T> void** IID_PPV_ARGS_Helper(T** pp) 
    {
        // make sure everyone derives from IUnknown
        static_cast<IUnknown*>(*pp);
        
        return reinterpret_cast<void**>(pp);
    }
}

#define IID_PPV_ARGS(ppType) __uuidof(**(ppType)), IID_PPV_ARGS_Helper(ppType)

#endif

#define IFACEMETHODIMP          __override STDMETHODIMP
#define IFACEMETHODIMP_(type)   __override STDMETHODIMP_(type)

#endif // WINVER 
